package org.fireflow2.designer.eclipse.editors;

import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;


public class SelectionSynchronizer
		extends AbstractSelectionProvider
		implements ISelectionChangedListener
{

	/**
	 * The registered {@link ISelectionProvider}s combined with their
	 * SelectionConverters.
	 */
//	private HashMap<ISelectionProvider, SelectionConverter> selectionProviders = new HashMap<ISelectionProvider, SelectionConverter>();

	/**
	 * The current selection. Must never be <code>null</code>.
	 */
	private ISelection currentSelection = StructuredSelection.EMPTY;

	/**
	 * Indicates that a new selection is currently dispatched.
	 */
	private boolean isDispatching = false;


	/**
	 * Creates a new instance.
	 */
	public SelectionSynchronizer()
	{
		// dispatch the selections on this object.
//		addSelectionChangedListener(this);
//		addSelectionProvider(this);
	}


	/**
	 * Adds a new SelectionProvider.
	 * 
	 * @param selectionProvider
	 *            The SelectionProvider.
	 */
	public void addSelectionProvider(ISelectionProvider selectionProvider)
	{
//		addSelectionProvider(selectionProvider, null);
		selectionProvider.setSelection(getSelection());

		// add the new provider
		selectionProvider.addSelectionChangedListener(this);
	}


	/**
	 * Adds a new SelectionProvider with a converter.
	 * 
	 * @param selectionProvider
	 *            The SelectionProvider.
	 * @param selectionConverter
	 *            The converter to convert the selection.
	 */
//	public void addSelectionProvider(ISelectionProvider selectionProvider,
//			SelectionConverter selectionConverter)
//	{
//		// synchronize the new provider with the current selection
//		selectionProvider.setSelection(getSelection());
//
//		// add the new provider
//		selectionProvider.addSelectionChangedListener(this);
//		//selectionProviders.put(selectionProvider, selectionConverter);
//	}


	/**
	 * Removes a SelectionProvider.
	 * 
	 * @param selectionProvider
	 *            The SelectionProvider.
	 */
	public void removeSelectionProvider(ISelectionProvider selectionProvider)
	{
		selectionProvider.removeSelectionChangedListener(this);
//		selectionProviders.remove(selectionProvider);
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
	 */
	public void selectionChanged(SelectionChangedEvent event)
	{
//		if (isDispatching)
//		{
//			return;
//		}

		ISelectionProvider source = event.getSelectionProvider();
		ISelection selection = event.getSelection();
//		StructuredSelection convertedSelection = StructuredSelection.EMPTY;
//		if (selection instanceof StructuredSelection){
//			List editPartList = ((IStructuredSelection) selection).toList();
//			ArrayList modelList = new ArrayList(editPartList.size());
//
//			for (Object element : editPartList)
//			{
//				if (element != null && element instanceof EditPart)
//				{
//					modelList.add(((EditPart) element).getModel());
//				}
//			}
//
//			convertedSelection =  new StructuredSelection(modelList);
//		}
		
		this.setSelection(selection);
//		SelectionConverter sourceConverter = selectionProviders.get(source);
//		if (sourceConverter != null)
//		{
//			selection = sourceConverter.convertFromTargetSelection(selection);
//		}

//		dispatchSelection(selection, source);
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
	 */
	public ISelection getSelection()
	{
		return currentSelection;
	}


	/**
	 * Sets a selection for all registered {@link #selectionProviders}.
	 * 
	 * @param selection
	 *            The new selection. The selection must not be <code>null</code>. To
	 *            clear selections use {@link StructuredSelection#EMPTY}.
	 */
	public void setSelection(ISelection selection)
	{
		assert selection != null;

		if (currentSelection == selection)
		{
			return;
		}

		currentSelection = selection;
		fireSelectionChanged(new SelectionChangedEvent(this, selection));
	}


	/**
	 * Dispatches a selection to all registered {@link #selectionProviders}.
	 * 
	 * @param selection
	 *            The new selection.
	 * @param source
	 *            The source provider that changed the selection. It is ignored from the
	 *            dispatching. May be <code>null</code>.
	 */
//	private void dispatchSelection(ISelection selection, ISelectionProvider source)
//	{
//		if (isDispatching)
//		{
//			return;
//		}
//
//		isDispatching = true;
//		for (Entry<ISelectionProvider, SelectionConverter> entry : selectionProviders
//				.entrySet())
//		{
//			if (entry.getKey() != source)
//			{
//				ISelection targetSelection;
//				if (entry.getValue() == null)
//				{
//					targetSelection = selection;
//				}
//				else
//				{
//					targetSelection = entry.getValue()
//							.convertToTargetSelection(selection);
//				}
//
//				entry.getKey().setSelection(targetSelection);
//			}
//		}
//		isDispatching = false;
//	}
}
